package org.twndmv.it;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import java.util.List;
import java.util.Properties;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.twndmv.bo.Sex;
import org.twndmv.dto.PersonDTO;
import org.twndmv.dto.PhysicalDetailsDTO;
import org.twndmv.ejb.DmvTestUtilRemote;
import org.twndmv.ejb.PersonMgmtRemote;

public class PersonMgmtIT {
	private static Log log = LogFactory.getLog(PersonMgmtIT.class);
	private Context jndi;

	private static final String adminUser = System.getProperty("admin.user",
			"admin1");
	private static final String knownUser = System.getProperty("known.user",
			"known");
	private static final String kathyUser = System.getProperty("kathy.user",
			"kathy");
	private static final String sherriUser = System.getProperty("sherri.user",
			"sherri");
	private static final String raleighUser = System.getProperty(
			"raleigh.user", "sysRaleigh");
	private static final String mayberryUser = System.getProperty(
			"mayberry.user", "sysMayberry");
	private static final String andyUser = System.getProperty("andy.user",
			"andy");
	private static final String barneyUser = System.getProperty("barney.user",
			"barney");
	private static final String gomerUser = System.getProperty("gomer.user",
			"gomer");
	private static final String password = System.getProperty("password",
			"password");

	private static final String dmvPersonJNDI = System
			.getProperty("jndi.name.person",
					"twnDmvEAR/twnDmvEJB/PersonMgmtEJB!org.twndmv.ejb.PersonMgmtRemote");
	private static final String dmvTestUtilJNDI = System
			.getProperty("jndi.name.dmvTestUtil",
					"twnDmvEAR/twnDmvEJB/DmvTestUtilEJB!org.twndmv.ejb.DmvTestUtilRemote");

	private DmvTestUtilRemote testUtil;

	private PersonMgmtRemote personManager;

	private Context runAs(String username, String password)
			throws NamingException {
		if (jndi != null) {
			jndi.close();
		}
		Properties env = new Properties();
		if (username != null) {
			env.put(Context.SECURITY_PRINCIPAL, username);
			env.put(Context.SECURITY_CREDENTIALS, password);
		}
		log.debug(String.format("%s env=%s", username == null ? "anonymous"
				: username, env));
		jndi = new InitialContext(env);
		return jndi;
	}

	@Before
	public void setUp() throws Exception {
		log.debug("===== TestDmvIT.init =====");
		jndi = runAs(adminUser, password);
		jndi.lookup("/"); // do a quick comms check of JNDI

		testUtil = (DmvTestUtilRemote) jndi.lookup(dmvTestUtilJNDI);
		personManager = (PersonMgmtRemote) jndi.lookup(dmvPersonJNDI);

		assertNotNull(testUtil);
		assertNotNull(personManager);
		testUtil.resetAll();
	}

	/**
	 * It is important to close the JNDI context in between tests
	 */
	@After
	public void tearDown() throws NamingException {
		if (jndi != null) {
			jndi.close();
			jndi = null;
		}
	}

	@Test
	public void testPersonManager() throws NamingException {

		jndi = runAs(sherriUser, password);
		PersonDTO testPerson = new PersonDTO();
		testPerson.setFirstName("Steve");
		testPerson.setMiddleName("Danger");
		testPerson.setLastName("Jobs");
		PhysicalDetailsDTO testDetails = new PhysicalDetailsDTO();
		testDetails.setHeight(64);
		testDetails.setWeight(180);
		testDetails.setSEX(Sex.MALE);
		testPerson.setPhysicalDetails(testDetails);
		personManager.createPerson(testPerson);
		jndi = runAs(mayberryUser, password);
		List<PersonDTO> resultPeeps = personManager.getPeopleByLastName("Jobs");
		assertNotNull(resultPeeps);
		assertEquals(1, resultPeeps.size());
		PersonDTO result = resultPeeps.get(0);
		assertNotNull(result);
		assertFalse(result.getMiddleName().equalsIgnoreCase("Caution"));
		result.setMiddleName("Caution");
		jndi = runAs(kathyUser, password);
		personManager.updatePerson(result);
		jndi = runAs(mayberryUser, password);
		PersonDTO peep = personManager.getPersonByID(result.getId());
		assertTrue(result.getFirstName().equalsIgnoreCase(peep.getFirstName()));
		assertTrue(result.getMiddleName().equalsIgnoreCase(peep.getMiddleName()));
		assertTrue(result.getLastName().equalsIgnoreCase(peep.getLastName()));

	}
}
